package com.unsins.core.basedomain;

import com.unsins.core.utils.GenericsUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.springframework.dao.DataAccessException;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: odpsoft
 * Date: 2008-11-27
 * Time: 11:20:34
 * To change this template use File | Settings | File Templates.
 */
public class HibernateEntityRepository<T> extends HibernateGenericRepository implements IEntityRepository<T> {
    protected final Logger logger = Logger.getLogger(this.getClass());
    protected Class<T> entityClass;// DAO所管理的Entity类型.

    /**
     * 在构造函数中将泛型T.class赋给entityClass.
     */
    public HibernateEntityRepository() {
        entityClass = GenericsUtils.getSuperClassGenricType(getClass());
    }

    /**
     * 取得entityClass.JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
     */
    protected Class<T> getEntityClass() {
        return entityClass;
    }

    /**
     * 根据ID获取对象.
     *
     * @see HibernateGenericRepository#getId(Class,Object)
     */
    public T get(Serializable id) {
        return get(getEntityClass(), id);
    }

    /**
     * 获取全部对象
     *
     * @see HibernateGenericRepository#getAll(Class)
     */
    public List<T> getAll() {
        return getAll(getEntityClass());
    }

    /**
     * 获取全部对象,带排序参数.
     *
     * @see HibernateGenericRepository#getAll(Class,String,boolean)
     */
    public List<T> getAll(String orderBy, boolean isAsc) {
        return getAll(getEntityClass(), orderBy, isAsc);
    }

    /**
     * 根据ID移除对象.
     *
     * @see HibernateGenericRepository#removeById(Class,Serializable)
     */
    public void removeById(Serializable id) {
        removeById(getEntityClass(), id);
    }

    /**
     * 取得Entity的Criteria.
     *
     * @see HibernateGenericRepository#createCriteria(Class,Criterion[])
     */
    public Criteria createCriteria(Criterion... criterions) {
        return createCriteria(getEntityClass(), criterions);
    }

    /**
     * 取得Entity的Criteria,带排序参数.
     *
     * @see HibernateGenericRepository#createCriteria(Class,String,boolean,Criterion[])
     */
    public Criteria createCriteria(String orderBy, boolean isAsc,
                                   Criterion... criterions) {
        return createCriteria(getEntityClass(), orderBy, isAsc, criterions);
    }

    /**
     * 根据属性名和属性值查询对象.
     *
     * @return 符合条件的对象列表
     * @see HibernateGenericRepository#findBy(Class,String,Object)
     */
    public List<T> findBy(String propertyName, Object value) {
        return findBy(getEntityClass(), propertyName, value);
    }

    /**
     * 根据属性名和属性值查询对象,带排序参数.
     *
     * @return 符合条件的对象列表
     * @see HibernateGenericRepository#findBy(Class,String,Object,String,boolean)
     */
    public List<T> findBy(String propertyName, Object value, String orderBy,
                          boolean isAsc) {
        return findBy(getEntityClass(), propertyName, value, orderBy, isAsc);
    }

    /**
     * 根据属性名和属性值查询单个对象.
     *
     * @return 符合条件的唯一对象 or null
     * @see HibernateGenericRepository#findUniqueBy(Class,String,Object)
     */
    public T findUniqueBy(String propertyName, Object value) {
        return findUniqueBy(getEntityClass(), propertyName, value);
    }

    /**
     * 判断对象某些属性的值在数据库中唯一.
     *
     * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
     * @see HibernateGenericRepository#isUnique(Class,Object,String)
     */
    public boolean isUnique(Object entity, String uniquePropertyNames) {
        return isUnique(getEntityClass(), entity, uniquePropertyNames);
    }

    /**
     * ************************************************************************
     *
     * @see IEntityRepository#findAllByMapKey(java.lang.Class,
     *      java.util.Map)
     */
    public List<T> findAllByMapKey(Class entity, Map<String, String> keymap)
            throws DataAccessException {
        StringBuffer buffer = new StringBuffer("from ");
        buffer.append(getTableNameFromClass(entity));
        buffer.append(" where ");
        Set<String> keys = keymap.keySet();
        Object[] values = new String[keys.size()];
        int i = 0;

        for (String key : keys) {
            buffer.append(key);
            buffer.append("=? and ");
            values[i] = keymap.get(key);

            i++;
        }

        String hql = buffer.toString();
        if (i > 0) {
            String temp = buffer.toString();
            hql = temp.substring(0, buffer.toString().lastIndexOf("and"));
        }

        return this.find(hql, values);
    }

    private String getTableNameFromClass(Class entity) {
        String className = entity.getName();

        return className.substring(className.lastIndexOf(".") + 1);
    }

    /* *
     * @see com.esoft.core.dao.EntityDao#findBy(java.lang.String, java.lang.Object[])
     */
    public List<T> findBy(String hql, Object... values) {
        return find(hql, values);
    }

}
